package com.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.demo.mapper.ScheduleMapper;
import com.demo.mapper.ClassroomMapper;
import com.demo.mapper.TeacherMapper;
import com.demo.mapper.CourseMapper;
import com.demo.mapper.TimeSlotMapper;
import com.demo.pojo.entity.Classroom;
import com.demo.pojo.entity.Teacher;
import com.demo.pojo.entity.Course;
import com.demo.pojo.entity.TimeSlot;
import com.demo.pojo.entity.Schedule;
import com.demo.service.ScheduleStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 排课统计服务实现类
 */
@Service
public class ScheduleStatisticsServiceImpl implements ScheduleStatisticsService {
    
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private ClassroomMapper classroomMapper;
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private TimeSlotMapper timeSlotMapper;

    private String resolveSemesterOrFallback(String requested) {
        List<String> candidates = new ArrayList<>();
        if (requested != null && !requested.isEmpty()) {
            candidates.add(requested);
        }
        candidates.add("advanced");
        candidates.add("2025-1");
        for (String sem : candidates) {
            Long count = timeSlotMapper.selectCount(new QueryWrapper<TimeSlot>().eq("semester", sem).eq("status", 1));
            if (count != null && count > 0L) {
                return sem;
            }
        }
        return requested; // fallback to original, even if empty
    }
    
    @Override
    public Map<String, Object> getClassroomUtilizationStats(String semester) {
        Map<String, Object> stats = new HashMap<>();
        
        // 按学期过滤（带回退）
        String usedSemester = resolveSemesterOrFallback(semester);
        QueryWrapper<Schedule> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("time_slot_id", "select time_slot_id from time_slot where semester='" + usedSemester + "' and status=1");
        List<Schedule> schedules = scheduleMapper.selectList(queryWrapper);
        if (schedules == null || schedules.isEmpty()) {
            // 学期下没有数据时，退化为全量统计
            schedules = scheduleMapper.selectList(new QueryWrapper<>());
            usedSemester = usedSemester + "|ALL";
        }
        
        // 计算教室使用次数
        Map<Long, Long> classroomUsage = schedules.stream()
                .collect(Collectors.groupingBy(Schedule::getClassroomId, Collectors.counting()));

        // 当学期总可用时段数（所有教室共享时段，因此对每间教室理论时段相同）
        long totalAvailableSlots = timeSlotMapper.selectCount(
                new QueryWrapper<TimeSlot>()
                        .eq("semester", usedSemester)
                        .eq("status", 1)
        );
        
        // 组装前端需要的数据结构
        List<Map<String, Object>> classroomList = new ArrayList<>();
        classroomUsage.forEach((classroomId, used) -> {
            Map<String, Object> row = new HashMap<>();
            Classroom room = classroomMapper.selectById(classroomId);
            row.put("name", room != null ? room.getClassroomName() : ("教室" + classroomId));
            row.put("usedSlots", used);
            int utilization = (totalAvailableSlots > 0)
                    ? (int) Math.round((used * 100.0) / totalAvailableSlots)
                    : 0;
            // 只要该教室被使用过，最低显示 1%
            if (utilization == 0 && used > 0) {
                utilization = 1;
            }
            row.put("utilization", Math.min(100, utilization));
            row.put("usedSlots", used);
            row.put("totalSlots", totalAvailableSlots);
            classroomList.add(row);
        });

        int avgUtilization = 0;
        if (!classroomList.isEmpty()) {
            avgUtilization = (int) Math.round(classroomList.stream().mapToInt(m -> (int) m.get("utilization")).average().orElse(0));
        }
        
        stats.put("classroomList", classroomList);
        stats.put("averageUtilization", avgUtilization);
        stats.put("semesterUsed", usedSemester);
        
        return stats;
    }
    
    @Override
    public Map<String, Object> getTeacherWorkloadStats(String semester) {
        Map<String, Object> stats = new HashMap<>();
        
        // 按学期过滤（带回退）
        String usedSemester = resolveSemesterOrFallback(semester);
        QueryWrapper<Schedule> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("time_slot_id", "select time_slot_id from time_slot where semester='" + usedSemester + "' and status=1");
        List<Schedule> schedules = scheduleMapper.selectList(queryWrapper);
        if (schedules == null || schedules.isEmpty()) {
            schedules = scheduleMapper.selectList(new QueryWrapper<>());
            usedSemester = usedSemester + "|ALL";
        }
        
        // 计算教师工作量
        Map<Long, Long> teacherWorkload = schedules.stream()
                .collect(Collectors.groupingBy(Schedule::getTeacherId, Collectors.counting()));
        
        long totalSchedules = schedules.size();
        int activeTeachers = teacherWorkload.size();
        int averageWorkload = activeTeachers > 0 ? (int) Math.round((double) totalSchedules / activeTeachers) : 0;

        // 组装前端 teacherList
        List<Map<String, Object>> teacherList = new ArrayList<>();
        long maxWork = teacherWorkload.values().stream().mapToLong(v -> v).max().orElse(0);
        teacherWorkload.forEach((tid, hours) -> {
            Map<String, Object> row = new HashMap<>();
            Teacher t = teacherMapper.selectById(tid);
            row.put("teacherName", t != null ? t.getTeName() : ("教师" + tid));
            row.put("totalHours", hours);
            int percentage = maxWork > 0 ? (int) Math.round(hours * 100.0 / maxWork) : 0;
            row.put("workloadPercentage", percentage);
            teacherList.add(row);
        });

        stats.put("teacherList", teacherList);
        stats.put("averageWorkload", averageWorkload);
        stats.put("semesterUsed", usedSemester);
        
        return stats;
    }
    
    @Override
    public Map<String, Object> getCourseDistributionStats(String semester) {
        Map<String, Object> stats = new HashMap<>();
        
        // 按学期过滤（带回退）
        String usedSemester = resolveSemesterOrFallback(semester);
        QueryWrapper<Schedule> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("time_slot_id", "select time_slot_id from time_slot where semester='" + usedSemester + "' and status=1");
        List<Schedule> schedules = scheduleMapper.selectList(queryWrapper);
        if (schedules == null || schedules.isEmpty()) {
            schedules = scheduleMapper.selectList(new QueryWrapper<>());
            usedSemester = usedSemester + "|ALL";
        }
        
        // 计算课程类型分布（去重课程）
        Map<String, Long> typeDistribution = new HashMap<>();
        Set<Long> countedCourseIds = new HashSet<>();
        for (Schedule s : schedules) {
            if (s.getCourseId() == null || countedCourseIds.contains(s.getCourseId())) continue;
            countedCourseIds.add(s.getCourseId());
            Course c = courseMapper.selectById(s.getCourseId());
            String type = c != null && c.getCourseType() != null ? c.getCourseType() : "其他";
            typeDistribution.put(type, typeDistribution.getOrDefault(type, 0L) + 1);
        }
        
        long total = typeDistribution.values().stream().mapToLong(v -> v).sum();
        List<Map<String, Object>> distribution = new ArrayList<>();
        typeDistribution.forEach((type, count) -> {
            Map<String, Object> row = new HashMap<>();
            row.put("type", type);
            row.put("count", count);
            int percent = total > 0 ? (int) Math.round(count * 100.0 / total) : 0;
            row.put("percentage", percent);
            distribution.add(row);
        });

        stats.put("totalCourses", countedCourseIds.size());
        stats.put("distribution", distribution);
        stats.put("semesterUsed", usedSemester);
        
        return stats;
    }
    
    @Override
    public Map<String, Object> getScheduleQualityAnalysis(String semester) {
        Map<String, Object> analysis = new HashMap<>();
        
        // 按学期过滤（带回退）
        String usedSemester = resolveSemesterOrFallback(semester);
        QueryWrapper<Schedule> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("time_slot_id", "select time_slot_id from time_slot where semester='" + usedSemester + "' and status=1");
        List<Schedule> schedules = scheduleMapper.selectList(queryWrapper);
        if (schedules == null || schedules.isEmpty()) {
            schedules = scheduleMapper.selectList(new QueryWrapper<>());
            usedSemester = usedSemester + "|ALL";
        }
        
        // 计算冲突数量
        int teacherConflicts = 0;
        int classroomConflicts = 0;
        int studentConflicts = 0;
        
        for (int i = 0; i < schedules.size(); i++) {
            for (int j = i + 1; j < schedules.size(); j++) {
                Schedule schedule1 = schedules.get(i);
                Schedule schedule2 = schedules.get(j);
                
                if (schedule1.getTeacherId().equals(schedule2.getTeacherId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    teacherConflicts++;
                }
                
                if (schedule1.getClassroomId().equals(schedule2.getClassroomId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    classroomConflicts++;
                }
                
                if (schedule1.getClazzId().equals(schedule2.getClazzId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    studentConflicts++;
                }
            }
        }
        
        // 计算质量分数
        double qualityScore = calculateQualityScore(schedules, teacherConflicts, classroomConflicts, studentConflicts);
        
        int totalConflicts = teacherConflicts + classroomConflicts + studentConflicts;
        int timeConflictRate = schedules.size() > 0 ? (int) Math.round(totalConflicts * 100.0 / schedules.size()) : 0;
        // 复用教室平均利用率
        Map<String, Object> clsStats = getClassroomUtilizationStats(semester);
        int avgUtil = (int) clsStats.getOrDefault("averageUtilization", 0);

        analysis.put("timeConflictRate", timeConflictRate);
        analysis.put("classroomUtilization", avgUtil);
        analysis.put("teacherSatisfaction", 85); // 简化：示意值，可接教师偏好后计算
        analysis.put("studentSatisfaction", 78); // 简化：示意值
        analysis.put("semesterUsed", usedSemester);
        
        return analysis;
    }
    
    @Override
    public Map<String, Object> getConflictStats(String semester) {
        Map<String, Object> stats = new HashMap<>();
        
        // 按学期过滤（带回退）
        String usedSemester = resolveSemesterOrFallback(semester);
        QueryWrapper<Schedule> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("time_slot_id", "select time_slot_id from time_slot where semester='" + usedSemester + "' and status=1");
        List<Schedule> schedules = scheduleMapper.selectList(queryWrapper);
        if (schedules == null || schedules.isEmpty()) {
            schedules = scheduleMapper.selectList(new QueryWrapper<>());
            usedSemester = usedSemester + "|ALL";
        }
        
        // 统计各种冲突
        Map<String, Integer> conflictTypes = new HashMap<>();
        conflictTypes.put("teacherConflicts", 0);
        conflictTypes.put("classroomConflicts", 0);
        conflictTypes.put("studentConflicts", 0);
        
        for (int i = 0; i < schedules.size(); i++) {
            for (int j = i + 1; j < schedules.size(); j++) {
                Schedule schedule1 = schedules.get(i);
                Schedule schedule2 = schedules.get(j);
                
                if (schedule1.getTeacherId().equals(schedule2.getTeacherId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    conflictTypes.put("teacherConflicts", conflictTypes.get("teacherConflicts") + 1);
                }
                
                if (schedule1.getClassroomId().equals(schedule2.getClassroomId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    conflictTypes.put("classroomConflicts", conflictTypes.get("classroomConflicts") + 1);
                }
                
                if (schedule1.getClazzId().equals(schedule2.getClazzId()) &&
                    schedule1.getTimeSlotId().equals(schedule2.getTimeSlotId())) {
                    conflictTypes.put("studentConflicts", conflictTypes.get("studentConflicts") + 1);
                }
            }
        }
        
        int totalConflicts = conflictTypes.values().stream().mapToInt(Integer::intValue).sum();
        
        stats.put("totalConflicts", totalConflicts);
        stats.put("conflictTypes", conflictTypes);
        stats.put("conflictRate", schedules.size() > 0 ? (double) totalConflicts / schedules.size() : 0.0);
        stats.put("semesterUsed", usedSemester);
        
        return stats;
    }
    
    /**
     * 计算质量分数
     */
    private double calculateQualityScore(List<Schedule> schedules, int teacherConflicts, 
                                       int classroomConflicts, int studentConflicts) {
        if (schedules.isEmpty()) return 0.0;
        
        int totalConflicts = teacherConflicts + classroomConflicts + studentConflicts;
        double conflictRate = (double) totalConflicts / schedules.size();
        
        // 质量分数 = 1 - 冲突率
        return Math.max(0.0, 1.0 - conflictRate);
    }
    
    /**
     * 获取质量等级
     */
    private String getQualityLevel(double qualityScore) {
        if (qualityScore >= 0.9) return "优秀";
        if (qualityScore >= 0.8) return "良好";
        if (qualityScore >= 0.7) return "一般";
        if (qualityScore >= 0.6) return "较差";
        return "很差";
    }
}











